#include "Hearts.h"
#include "AnimatorHolder.h"
#include "AnimationFilmHolder.h"
#include "Scores.h"
#include "HeartHolder.h"
#include "Popeye.h"
#include "AudioHolder.h"
#include "AI.h"

bool dummy_bool;

Hearts::Hearts(Dim _x, Dim _y, AnimationFilm* film, animid_t id, 
	FrameRangeAnimation *_fallAnimation, FrameRangeAnimator *_fallAnimator, 
	FlashingAnimation *_flashAnimation, FlashingAnimator *_flashAnimator,
	TrophyDisplay *_tdisplay) : 
		Sprite(_x,_y,film), id(id), 
		fallAnimation(_fallAnimation), fallAnimator(_fallAnimator),
		flashAnimation(_flashAnimation), flashAnimator(_flashAnimator),
		trophyDisplay(_tdisplay) {
	frameNo = currFilm->GetTotalFrames();
	SetFrame(0);
	canMove = true;
	isFalling = false;
	taken = false;
	isFlashing = false;
	broken = false;
	callbacks = 0;
}

Hearts::~Hearts(void) {}

void Hearts::StartFlashing(void) {
	assert(fallAnimator->HasFinished());

	isFalling = false;
	isFlashing = true;
	currFilm = (AnimationFilm *)AnimationFilmHolder::GetSingleton()->GetFilm("heart");
	flashAnimation->SetRepetitions(25);
	AnimatorData* data = new AnimatorData(this, &HeartHolder::heartBroken);
	flashAnimator->SetOnFinish(HeartBreaks, (void *)data);
	flashAnimator->Start(this, flashAnimation, Timer::getgametime());
	AnimatorHolder::MarkAsRunning(flashAnimator);
	AudioHolder::ChangeToSound("danger");
}

void Hearts::StopFlashing(void) {
	isFlashing = false;
	flashAnimator->Stop();
	AnimatorHolder::DelayedSuspention(flashAnimator);
	AnimatorHolder::Cancel(flashAnimator);
}

void Hearts::Move(int dx, int dy) {
	if(!taken) {
		Platform *p = PlatformHolder::CheckPlatformCollision(this);
		if(p) {
			if (p->CollidesWithSea(this) && isFalling) {
				StopFalling();
				StartFlashing();
				this->platform = p;
				p->AlignWithPlatform(this);
				dx=0;
				dy=0;
			}
		}
		dx = 5;
		if(callbacks == 20)
			callbacks = 0;
		if(callbacks <= 10)
			dx = -5;
		callbacks++;
		
		Sprite::Move(dx, dy);
	}
}

void Hearts::StartFalling(void) {
	isFalling = true;
	isFlashing = false;
	currFilm = (AnimationFilm *)AnimationFilmHolder::GetSingleton()->GetFilm("hearts");
	fallAnimator->Start(this, fallAnimation, Timer::getgametime());
	AnimatorHolder::MarkAsRunning(fallAnimator);
}

void Hearts::StopFalling(void) {
	isFalling = false;
	fallAnimator->Stop();
	AnimatorHolder::DelayedSuspention(fallAnimator);
	AnimatorHolder::Cancel(fallAnimator);
}

int Hearts::GivePoints(void) {
	//niania, scale will break this...
	if(this->y<216) return 500;
	else if(this->y<280) return 300;
	else if(this->y<344) return 100;
	else if(this->y<408) return 50;
	else return 0;
}

bool Hearts::Flashes(void) {
	return isFlashing;
}

void Hearts::CollisionAction(Sprite *s) {
	Popeye *p = (Popeye*)s;
	if(!taken) {
		taken = true;
		
		int multiplier = 1;
		if(p->getMode() == spinach) multiplier = 2;
		Scores::increaseScore(this->GivePoints()*multiplier);
		//TODO:add to trophy display
		this->trophyDisplay->PlaceOnNextSlot(this);
		//this->SetVisibility(false);
		if(!fallAnimator->HasFinished())
			StopFalling();
		//need to take care the callback function, else we
		//end up with a game over
		AnimatorData* data = new AnimatorData(this, (bool *)NULL);
		flashAnimator->SetOnFinish(HeartBreaks, (void *)data);
		if(!flashAnimator->HasFinished()) {
			AudioHolder::ChangeToSound("level01");
			StopFlashing();
		}
		//HeartHolder::Remove(this);
	}
};

void Hearts::ResetToDefaultFilm(void) {
	currFilm = (AnimationFilm *)AnimationFilmHolder::GetSingleton()->GetFilm("heart");
}

void Hearts::HeartBreaks(Animator *anim, void *closure) {
	AnimatorData *data = (AnimatorData*)closure;
	Sprite *s = data->first;
	anim->Stop();
	AnimatorHolder::DelayedSuspention(anim);
	AnimatorHolder::Cancel(anim); //FIXME: will not really be removed, need delayed remove
	if(data->second == NULL) return;
	s->SetAnimationFilm((AnimationFilm *)AnimationFilmHolder::GetSingleton()->GetFilm("heart_breaks"));
	s->SetVisibility(true);
	(*data->second) = true;
	AI::PopeyeDies();
};

void Hearts::Pause(timestamp_t currtime) {
	lastTime = currtime;
	if(!fallAnimator->HasFinished())
		AnimatorHolder::DelayedSuspention(fallAnimator);
	if(!flashAnimator->HasFinished())
		AnimatorHolder::DelayedSuspention(flashAnimator);
}

void Hearts::Resume(void) {
	timestamp_t pauseOffset = (Timer::getsystime()-lastTime);
	if(!fallAnimator->HasFinished()) {
		fallAnimator->TimeShift(pauseOffset);
		AnimatorHolder::MarkAsRunning(fallAnimator);
	}
	else if(!flashAnimator->HasFinished()) {
		flashAnimator->TimeShift(pauseOffset);
		AnimatorHolder::MarkAsResumed(flashAnimator);
	}
}